package com.yyfax.pay.third.facade.fuioudeposit;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.yyfax.framework.common.Log;
import com.yyfax.pay.common.constants.FuiouDepositConstant;
import com.yyfax.pay.common.enums.FuiouDepositRspCodeEnum;
import com.yyfax.pay.common.exception.PayExceptionCode;
import com.yyfax.pay.common.model.vo.PayRspCodeVO;
import com.yyfax.pay.depository.domain.FuiouCharge;
import com.yyfax.pay.depository.domain.FuiouWithdraw;
import com.yyfax.pay.depository.vo.EntrustTradeVO;
import com.yyfax.pay.depository.vo.FuiouResponseVO;
import com.yyfax.pay.third.model.to.fuioudeposit.FuiouDepositConfigExt;
import com.yyfax.pay.third.model.to.fuioudeposit.xml.BasePlain;
import com.yyfax.pay.third.model.to.fuioudeposit.xml.RootXMLRsp;

/**
 * 富友存管委托充值/提现服务
 *
 * @author yejc
 * @date 2017-10-10
 * @since v1.0.0
 */
@Service
public class FuiouDepositEntrustService {

	Logger logger = LoggerFactory.getLogger(getClass());

	@Resource
	private FuiouSignService fuiouSignService;

	@Resource
	private FuiouDepositService fuiouDepositService;

	@Resource
	private FuiouDepositConstant fuiouDepositConstant;

	/**
	 * 委托提现
	 *
	 * @author yejc
	 * @date 2017-10-10
	 * @since v2.0.0
	 * @return
	 */
	public PayRspCodeVO entrustWithdraw(FuiouWithdraw domain) {
		String op = "FuiouDepositEntrustService.entrustWithdraw";
		try {
			String merchantCode = domain.getMerchantCode();
			FuiouDepositConfigExt extInfo = fuiouSignService.getFuiouDepositConfig(merchantCode);
			// 构建请求参数
			EntrustTradeVO entrustChargeVO = buildEntrustReqParams(extInfo, domain.getBusiId(), domain.getLoginId(), String.valueOf(domain.getAmount()), fuiouDepositConstant.getEntrustWithdrawNotifyUrl(), domain.getRemark(), merchantCode);

			// 请求存管系统
			FuiouResponseVO resp = fuiouDepositService.postForResponseVO(entrustChargeVO, extInfo.getEntrustWithdrawUrl(), merchantCode);

			return parseResponse(resp);
		} catch (Exception e) {
			logger.error(Log.op(op).msg("【富友存管-委托提现】发送请求失败！").kv("busiId", domain.getBusiId()).toString(), e);
			return PayRspCodeVO.newInstance(PayExceptionCode.ERROR_PAY_FAIL.getCode(), PayExceptionCode.ERROR_PAY_FAIL.getDesc());
		}
	}

	/**
	 * 委托充值
	 *
	 * @author yejc
	 * @date 2017-10-11
	 * @since v2.0.0
	 * @param domain
	 * @return
	 */
	public PayRspCodeVO entrustCharge(FuiouCharge domain) {
		String op = "FuiouDepositEntrustService.entrustCharge";
		try {
			String merchantCode = domain.getMerchantCode();
			FuiouDepositConfigExt extInfo = fuiouSignService.getFuiouDepositConfig(merchantCode);
			// 构建请求参数
			EntrustTradeVO entrustChargeVO = buildEntrustReqParams(extInfo, domain.getBusiId(), domain.getLoginId(), String.valueOf(domain.getAmount()), fuiouDepositConstant.getEntrustChargeNotifyUrl(), domain.getRemark(), merchantCode);

			// 请求存管系统
			FuiouResponseVO resp = fuiouDepositService.postForResponseVO(entrustChargeVO, extInfo.getEntrustChargeUrl(), merchantCode);

			return parseResponse(resp);
		} catch (Exception e) {
			logger.error(Log.op(op).msg("【富友存管-委托充值】发送请求失败！").kv("busiId", domain.getBusiId()).toString(), e);
			return PayRspCodeVO.newInstance(PayExceptionCode.ERROR_PAY_FAIL.getCode(), PayExceptionCode.ERROR_PAY_FAIL.getDesc());
		}
	}

	/**
	 * 构建委托交易请求参数
	 *  @param extInfo
	 * @param busiId
	 * @param accountNo
	 * @param amount
	 * @param backNotifyUrl
	 * @param remark @return
	 * @param merchantCode
	 * */
	private EntrustTradeVO buildEntrustReqParams(FuiouDepositConfigExt extInfo, String busiId, String accountNo, String amount, String backNotifyUrl, String remark, String merchantCode) {
		EntrustTradeVO vo = new EntrustTradeVO();
		vo.setMerchantId(extInfo.getMerchantId());
		vo.setBusiId(busiId);
		vo.setAccountNo(accountNo);
		vo.setAmount(amount);
		vo.setBackNotifyUrl(backNotifyUrl);
		vo.setRemark(remark);
		vo.setSignature(fuiouSignService.getSign(merchantCode, vo));

		return vo;
	}

	/**
	 * 转换富友响应码为支付响应码,并判断超时、验签失败等情况
	 *
	 * @author yejc
	 * @date 2017-10-09
	 * @since v2.0.0
	 * @param resp
	 * @return
	 */
	private PayRspCodeVO parseResponse(FuiouResponseVO resp) {
		final String op = "FuiouDepositEntrustService.parseResponse";

		if (FuiouResponseVO.TIMEOUT.equals(resp.getResult())) {
			return PayRspCodeVO.newInstance(PayExceptionCode.WARN_REQ_TIME_OUT.getCode(), PayExceptionCode.WARN_REQ_TIME_OUT.getDesc());
		}

		if (FuiouResponseVO.INVALID_DATA.equals(resp.getResult())) {
			// 其他异常返回对应匹配后的响应消息
			return PayRspCodeVO.newInstance(PayExceptionCode.SYS_ERROR.getCode(), PayExceptionCode.SYS_ERROR.getDesc());
		}

		String result = resp.getContent();
		RootXMLRsp<BasePlain> fuiouRsp = (RootXMLRsp<BasePlain>) RootXMLRsp.fromXml(result, BasePlain.class);
		if (!FuiouDepositRspCodeEnum.SUCCESS.isValue(fuiouRsp.getPlain().getRspCode())) {
			// 不是成功的请求，即富友返回不是0000，打印一下响应信息，方便debug
			logger.warn(Log.op(op).msg("【富友存管】存管接口返回失败").kv("响应码", fuiouRsp.getPlain().getRspCode()).kv("响应消息", fuiouRsp.getPlain().getRspMsg()).kv("busiId", fuiouRsp.getPlain().getBusiId()).toString());
			if (FuiouDepositRspCodeEnum.ACCEPTED.getValue().equals(fuiouRsp.getPlain().getRspCode())) {
				// 0001 理论上不会出现，需要告警人工干预
				logger.error(Log.op(op).msg("委托交易，响应码出现0001，因为金额超过风控限制，需要人工干预！！").kv("busiId", fuiouRsp.getPlain().getBusiId()).toString());
			}
		}
		return fuiouDepositService.converToPayRspCode(fuiouRsp.getPlain().getRspCode());
	}
}
